<!--
 * @Description: 对话框
 * @Author: DHL
 * @Date: 2021-12-24 17:10:40
 * @LastEditors: DHL
 * @LastEditTime: 2022-12-22 11:00:47
-->

<template>
  <el-dialog
    v-model="myState.visible"
    :width="width"
    :destroy-on-close="destroyOnClose"
    :class="`tw-dialog-wrapper ${customClass} ${!myState.footer ? 'tw-dialog-none-footer' : ''}`"
    :fullscreen="myState.fullscreen"
    :draggable="true"
    :show-close="false"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    @open="handleOpen"
    @close="handleClose"
  >
    <template #header>
      <div class="title">{{ title }}</div>
      <div>
        <el-button
          text
          type="primary"
          class="tw-dialog__btn"
          :title="myState.fullscreen ? '还原' : '最大化'"
          :disabled="loading"
          @click="handleFullscreen"
          v-if="showZoom"
        >
          <svg-icon :iconClass="myState.fullscreen ? 'restore' : 'maximize'"></svg-icon>
        </el-button>
        <el-button
          text
          type="primary"
          class="tw-dialog__btn"
          title="关闭"
          :disabled="loading"
          @click="handleClose"
        >
          <svg-icon iconClass="close"></svg-icon>
        </el-button>
      </div>
    </template>

    <div
      class="tw-dialog__body"
      :style="bodyStyle"
      v-loading="loading"
      element-loading-background="var(--tw-mask-color)"
    >
      <template v-if="scrollbar">
        <el-scrollbar height="100%">
          <div class="tw-dialog__body-content" :style="bodyContentStyle">
            <slot></slot>
          </div>
        </el-scrollbar>
      </template>
      <template v-else>
        <slot></slot>
      </template>
    </div>

    <template #footer v-if="myState.footer">
      <slot name="footer"></slot>
      <div v-if="loading" class="tw-loading-mask"></div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
  import { computed, reactive, ref, useSlots } from 'vue'
  import { arrayRemoveItem } from '/@/utils/twUtils'

  interface Props {
    /**
     * 是否显示弹框
     * 默认值：false
     */
    modelValue: boolean

    /**
     * 标题
     * 默认值： ''
     */
    title: string

    /**
     * Dialog 的宽度
     * 默认值：50%
     */
    width?: string

    /**
     * 滚动条最大高度
     * 超出高度内容，出现滚动条
     */
    height?: string

    /**
     * 内容高度
     */
    heightContent?: string

    /**
     * 关闭时销毁 Dialog 中的元素
     * 默认值：true
     */
    destroyOnClose?: boolean

    /**
     * loading
     */
    loading?: boolean

    /**
     * 标题是否标显示最大化与还原按钮
     */
    showZoom?: boolean

    /**
     * 自定义className
     */
    customClass?: string

    /**
     * 是否加载滚动条
     */
    scrollbar?: boolean

    /**
     * 是否显示底部
     */
    footer?: boolean
  }

  const props = withDefaults(defineProps<Props>(), {
    modelValue: false,
    title: '',
    width: '50%',
    height: 'auto',
    destroyOnClose: true,
    loading: false,
    showZoom: true,
    customClass: '',
    scrollbar: true,
    footer: true
  })

  /**
   * 插槽集合
   */
  const slots = useSlots()

  /**
   * 插槽名称集合
   */
  const slotKeys = computed(() => {
    const slotKeys = Object.keys(slots)
    arrayRemoveItem(slotKeys, 'default')
    arrayRemoveItem(slotKeys, 'footer')
    return slotKeys
  })

  const emit = defineEmits(['open', 'opened', 'close', 'closed', 'zoom'])

  /**
   * 状态
   */
  const myState = reactive({
    visible: false,
    footer: false,
    fullscreen: false
  })

  watch(
    () => props.modelValue,
    (newValue) => {
      myState.visible = newValue
    },
    {
      immediate: true
    }
  )

  if (slots.footer && props.footer) {
    myState.footer = true
  }

  /**
   * body行内样式
   */
  const bodyStyle = ref()

  /**
   * body-content行内样式
   */
  const bodyContentStyle = ref()

  //////////////////////////////////////////////////
  // 函数
  //////////////////////////////////////////////////

  /**
   * 最大化
   */
  function handleFullscreen() {
    myState.fullscreen = !myState.fullscreen
    buildLayoutStyle()
    emit('zoom')
  }

  /**
   * body行内样式
   */
  function buildLayoutStyle() {
    bodyStyle.value = {}
    bodyContentStyle.value = {}

    if (props.height && !myState.fullscreen) {
      Object.assign(bodyStyle.value, {
        height: props.height
      })
    }

    if (props.heightContent && !myState.fullscreen) {
      Object.assign(bodyContentStyle.value, {
        height: props.heightContent
      })
    }
  }

  /**
   * 打开弹框
   */
  function handleOpen() {
    buildLayoutStyle()
    emit('open')
  }

  /**
   * 关闭弹框
   */
  function handleClose() {
    emit('close')
  }
</script>

<style lang="scss"></style>
